package dbsucxentW.pathProcessorW;

import java.sql.*;
import java.util.regex.*;
import java.util.ArrayList;
import java.util.HashMap;

public class SimpleXPathWithPosPred {

	class MyPath {
		public String path = "";

		public String pathWOpredicate = "";

		public int initPos = -1;

		public int endPos = -1;

		public int level = -1;

		public int predLevel = -1;
	}

	private String _StartWITH = "WITH V (LeafValue, PathID, BranchOrder, DeweyOrderSum, DocId, LeafOrder ) AS ( ";

	private String _ORDERBY = "ORDER BY DocId, DeweyOrderSum, Attr, AttrOrder ";

	private String _OPTION = "";

	private String _EndWITH = ") ";

	private String _SELECT1 = "SELECT V.*, 1 as Attr, 0 as AttrOrder ";

	private String _FROM1 = "FROM V ";

	private String _SELECT2 = "SELECT A.leafValue, A.pathID, V.branchOrder, V.DeweyOrderSum, A.DocId, A.LeafOrder, 0 as Attr, A.AttrOrder ";

	private String _FROM2 = "FROM Attribute A, V ";

	private String _WHERE2 = "WHERE A.DocId = V.DocId AND A.LeafOrder = V.LeafOrder \n"
			+ "\t AND A.PathID IN (#PathIDList#) ";

	private String _SELECT = "SELECT ";

	private String _FROM = "FROM ";

	private String _WHERE = "WHERE  ";

	private Connection dbconnection = null;

	private boolean hasStar = false;

	private boolean isAttribute = false;

	private boolean isSingleXML = false;

	private final String tabber = "   ";

	private ArrayList _FullXPath = new ArrayList();

	private int numTables = 0;

	private HashMap MyRValue = null;

	private String SQLQuery = "";

	/** Creates a new instance of SimpleXPathTranslator */
	public SimpleXPathWithPosPred(Connection dbCon, String XPath) {
		dbconnection = dbCon;
		isSingleXML = isSingleDoc();

		if (isSingleXML)
			MyRValue = loadRValue();

		// delete table templast and lastvalue

		if (XPath.contains("*"))
			hasStar = true;

		// Replace attribute() with @*
		// eg: /a/b/attribute() -> /a/b/@*
		if (XPath.endsWith("attribute()")) {
			XPath = XPath.replace("attribute()", "@*");
		}
		// Replace attribute::* with @*
		// eg: /a/b/attribute::* -> /a/b/@*
		if (XPath.endsWith("attribute::*")) {
			XPath = XPath.replace("attribute::*", "@*");
		}

		Pattern p = Pattern
				.compile("(/((([@a-zA-Z_0-9])+|\\*|@\\*)(\\[(position\\(\\)(>|<|(<=)|(>=)|=))?(([0-9])+( (to) ([0-9])+)?|(last\\(\\))((-)([0-9])+)?)\\])?)|/)+");
		Matcher m = p.matcher(XPath);

		if (m.matches()) {
			// contains only position predicate
			// eg: /a/b[1]/c/d[2]
			_FullXPath = splitXPathWithPosPredicate(XPath);
		}
		for (int i = 0; i < _FullXPath.size(); i++) {
			MyPath mypath = (MyPath) _FullXPath.get(i);
			String _CXPath = "", _dbCXPath = "";
			if (mypath.pathWOpredicate.contains("@")) {
				if (mypath.pathWOpredicate.contains("//")) {
					_CXPath = mypath.pathWOpredicate.substring(0, mypath.path
							.indexOf("@") - 1);
					_dbCXPath = _CXPath.replace("//", "#.%#.").replace("/",
							"#.").replace("*", "%").substring(1)
							+ "#";
					isAttribute = true;
				} else {
					_CXPath = mypath.pathWOpredicate.substring(0, mypath.path
							.indexOf("@") - 1);
					_dbCXPath = _CXPath.replace("/", "#.").replace("*", "%")
							.substring(1)
							+ "#";
					isAttribute = true;
				}
			} else if (mypath.pathWOpredicate.contains("//")) {
				_CXPath = mypath.pathWOpredicate;
				_dbCXPath = mypath.pathWOpredicate.replace("//", "#.%#.")
						.replace("/", "#.").replace("*", "%").substring(1)
						+ "#";
			} else {
				_CXPath = mypath.pathWOpredicate;
				_dbCXPath = mypath.pathWOpredicate.replace("/", "#.").replace(
						"*", "%").substring(1)
						+ "#";
			}

			if (i == 0) {
				if (i == (_FullXPath.size() - 1))
					SQLQuery = TranslateXPath(_CXPath, _dbCXPath, mypath, null,
							isAttribute, isSingleXML, true);
				else
					SQLQuery = TranslateXPath(_CXPath, _dbCXPath, mypath, null,
							isAttribute, isSingleXML, false);
			} else if (i == (_FullXPath.size() - 1))
				SQLQuery = TranslateXPath(_CXPath, _dbCXPath, mypath,
						(MyPath) _FullXPath.get(i - 1), isAttribute,
						isSingleXML, true);
			else
				SQLQuery = TranslateXPath(_CXPath, _dbCXPath, mypath,
						(MyPath) _FullXPath.get(i - 1), isAttribute,
						isSingleXML, false);

		}
	}

	public String getTranslatedSQL() {
		return SQLQuery;
	}

	private String TranslateXPath(String XPath, String DBXPath, MyPath mypath,
			MyPath myprevpath, boolean isAttribute, boolean isSingleDoc,
			boolean isLastStep) {

		boolean isElementPathExist = false;
		boolean isAttributePathExist = false;
		String ElementPathIDList = "", AttributePathIDList = "";

		try {
			Statement statement = dbconnection.createStatement();

			ResultSet results = statement
					.executeQuery("SELECT pathid, pathexp FROM PATH WHERE PATHEXP LIKE '"
							+ DBXPath + "%' AND PATHEXP NOT LIKE '%@%'");

			boolean first = true;
			while (results.next()) {
				if (first) {
					if (hasStar) {
						if (isXPathValid(XPath, results.getString("pathexp")
								.trim())) {
							ElementPathIDList += results.getString("Pathid");
							first = false;
							isElementPathExist = true;
						}
					} else {
						ElementPathIDList += results.getString("Pathid");
						first = false;
						isElementPathExist = true;
					}
				} else {
					if (hasStar) {
						if (isXPathValid(XPath, results.getString("pathexp")
								.trim())) {
							ElementPathIDList += ","
									+ results.getString("Pathid");
						}
					} else {
						ElementPathIDList += "," + results.getString("Pathid");
					}
				}
			}

			numTables++;
			if (numTables == 1) {
				_FROM += "PATHVALUE V1 ";
				_WHERE += "\n" + tabber + "V1.PathID IN (" + ElementPathIDList
						+ ") \n";
				if (mypath.initPos >= -1) {
					if (isSingleDoc) {
						Long rval = (Long) MyRValue.get(new Integer(
								mypath.predLevel - 1));

						if (mypath.initPos > -1)
							_WHERE += tabber + "AND V1.SiblingSum BETWEEN 0 + "
									+ mypath.initPos + " * (2 * CAST("
									+ rval.longValue() + " as BIGINT) - 1) "
									+ "AND 0 + " + mypath.endPos
									+ " * (2 * CAST(" + rval.longValue()
									+ " as BIGINT) - 1) - 1 \n";
						else
							_WHERE += tabber + "AND V1.SiblingSum >= 0 + "
									+ mypath.endPos + " * (2 * CAST("
									+ rval.longValue()
									+ " as BIGINT) - 1) - 1 \n";

					} else {
						_FROM += ", DocumentRValue R1 ";
						_WHERE += "" + tabber + "AND V1.DocID = R1.DocID \n";
						_WHERE += "" + tabber + "AND R1.Level = "
								+ mypath.level;

						if (mypath.initPos > -1)
							_WHERE += ""
									+ tabber
									+ "AND V1.SiblingSum BETWEEN 0 + "
									+ mypath.initPos
									+ " * (2 * CAST(R1.RVALUE as BIGINT) - 1) "
									+ "AND 0 + "
									+ mypath.endPos
									+ " * (2 * CAST(R1.RVALUE as BIGINT) - 1) - 1 \n";
						else
							_WHERE += ""
									+ tabber
									+ "AND V1.SiblingSum >= 0 + "
									+ mypath.endPos
									+ " * (2 * CAST(R1.RVALUE as BIGINT) - 1) - 1 \n";
					}
				} else if (mypath.initPos == -9999) {
					_FROM += ", LASTVALUE L1 ";
					_WHERE += "" + tabber + "AND V1.DocID = L1.DocID \n";
					_WHERE += "" + tabber + "AND L1.Level = R1.LEVEL ";
					_WHERE += "" + tabber + "AND V1.SiblingSum BETWEEN 0 + "
							+ mypath.initPos
							+ " * (2 * CAST(RVAL as BIGINT) - 1) " + "AND 0 + "
							+ mypath.endPos
							+ " * (2 * CAST(RVAL as BIGINT) - 1) - 1 \n";
				}
			} else if (ElementPathIDList.length() > 0) {
				_FROM += ", PATHVALUE V" + numTables + " ";
				_WHERE += "" + tabber + "AND V" + (numTables - 1)
						+ ".BranchOrder < " + myprevpath.level + " \n";
				_WHERE += "" + tabber + "AND V" + (numTables - 1)
						+ ".DocID = V" + numTables + ".DocID \n";
				_WHERE += "" + tabber + "AND V" + numTables + ".PathID IN ("
						+ ElementPathIDList + ") \n";
				if (mypath.initPos >= -1) {
					if (isSingleDoc) {
						Long rval = (Long) MyRValue.get(new Integer(
								mypath.predLevel - 1));
						Long rval2 = (Long) MyRValue.get(new Integer(
								myprevpath.level - 1));
						_WHERE += "" + tabber + "AND V" + numTables
								+ ".DeweyOrderSum BETWEEN V" + (numTables - 1)
								+ ".DeweyOrderSum - CAST(" + rval2.longValue()
								+ " as BIGINT) + 1 " + "AND V"
								+ (numTables - 1) + ".DeweyOrderSum + CAST("
								+ rval2.longValue() + " as BIGINT) - 1  \n";

						if (mypath.initPos > -1)
							_WHERE += "" + tabber + "AND V" + numTables
									+ ".SiblingSum BETWEEN V" + (numTables - 1)
									+ ".SiblingSum + " + mypath.initPos
									+ " * (2 * CAST(" + rval.longValue()
									+ " as BIGINT) - 1) " + "AND V"
									+ (numTables - 1) + ".SiblingSum + "
									+ mypath.endPos + " * (2 * CAST("
									+ rval.longValue()
									+ " as BIGINT) - 1) - 1 \n";
						else
							_WHERE += "" + tabber + "AND V" + numTables
									+ ".SiblingSum >= V" + (numTables - 1)
									+ ".SiblingSum + " + mypath.endPos
									+ " * (2 * CAST(" + rval.longValue()
									+ " as BIGINT) - 1) - 1 \n";
					} else {

						// for multiple documents
					}
				} else if (mypath.initPos == -9999) {
					_FROM += ", LASTVALUE L" + numTables + " ";
					_WHERE += "" + tabber + "AND V" + numTables + ".DocID = L"
							+ numTables + ".DocID \n";
					_WHERE += "" + tabber + "AND L" + numTables + ".Level = R"
							+ numTables + ".LEVEL ";
					_WHERE += "" + tabber + "AND V" + numTables
							+ ".SiblingSum BETWEEN 0 + " + mypath.initPos
							+ " * (2 * CAST(RVAL as BIGINT) - 1) " + "AND 0 + "
							+ mypath.endPos
							+ " * (2 * CAST(RVAL as BIGINT) - 1) - 1 \n";

					_WHERE += ""
							+ tabber
							+ "AND V"
							+ numTables
							+ ".DeweyOrderSum BETWEEN V"
							+ (numTables - 1)
							+ ".DeweyOrderSum - CAST(533751867279 as BIGINT) + 1 "
							+ "AND V"
							+ (numTables - 1)
							+ ".DeweyOrderSum + CAST(533751867279 as BIGINT) - 1  \n";
				}
			} else {
				numTables--;
			}

			_SELECT = "SELECT DISTINCT V" + numTables + ".LeafValue, V"
					+ numTables + ".PathID, V" + numTables + ".BranchOrder, "
					+ "V" + numTables + ".DeweyOrderSum, V" + numTables
					+ ".DocId,  V" + numTables + ".LeafOrder \n";

			// get attribute
			if (isAttribute) {
				if (mypath.path.contains("//")) {
					DBXPath = mypath.path.replace("//", "#.%#.").replace("/",
							"#.").replace("*", "%").substring(1)
							+ "#";
				} else {

					DBXPath = mypath.path.replace("/", "#.").replace("*", "%")
							.substring(1)
							+ "#";
				}
				results = statement
						.executeQuery("SELECT pathid, pathexp FROM PATH WHERE PATHEXP LIKE '"
								+ DBXPath + "%' AND PATHEXP LIKE '%@%'");
			} else {
				results = statement
						.executeQuery("SELECT pathid, pathexp FROM PATH WHERE PATHEXP LIKE '"
								+ DBXPath + "%' AND PATHEXP LIKE '%@%'");
			}

			first = true;

			while (results.next()) {
				if (first) {
					if (hasStar) {
						if (isXPathValid(mypath.path, results.getString(
								"pathexp").trim())) {
							AttributePathIDList = results.getString("Pathid");
							first = false;
							isAttributePathExist = true;
						}
					} else {
						AttributePathIDList = results.getString("Pathid");
						first = false;
						isAttributePathExist = true;
					}
				} else {
					if (hasStar) {
						if (isXPathValid(mypath.path, results.getString(
								"pathexp").trim())) {
							AttributePathIDList += ","
									+ results.getString("Pathid");
						}
					} else {
						AttributePathIDList += ","
								+ results.getString("Pathid");
					}
				}
			}

			if (!isLastStep)
				AttributePathIDList = "";
			results.close();
			statement.close();

		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			// JOptionPane.showMessageDialog(null,ex.getMessage(), "Error",
			// JOptionPane.ERROR_MESSAGE);
			// return "ERROR";
		}
		if (isLastStep) {
			if (isElementPathExist && isAttributePathExist) {
				_WHERE2 = _WHERE2.replace("#PathIDList#", AttributePathIDList);
				String query = "";
				if (isAttribute) {
					query = _StartWITH + "\n" + "" + tabber + "" + _SELECT
							+ "\n" + "" + tabber + "" + _FROM + "\n" + ""
							+ tabber + "" + _WHERE + "\n" + _EndWITH + " "
							+ _SELECT2 + "\n" + _FROM2 + "\n" + _WHERE2 + "\n"
							+ _ORDERBY + "\nOPTION (FORCE ORDER) \n";
				} else {
					query = _StartWITH + "\n" + "" + tabber + "" + _SELECT
							+ "\n" + "" + tabber + "" + _FROM + "\n" + ""
							+ tabber + "" + _WHERE + "\n" + _EndWITH + " "
							+ _SELECT1 + "\n" + _FROM1 + "\n" + "UNION ALL \n"
							+ _SELECT2 + "\n" + _FROM2 + "\n" + _WHERE2 + "\n"
							+ _ORDERBY + "\nOPTION (FORCE ORDER) \n";
				}
				return query;
			} else if (isElementPathExist && !isAttributePathExist
					&& (numTables == 1)) {
				return _SELECT + "\n" + _FROM + "\n" + _WHERE + "\n"
						+ "ORDER BY DocId, DeweyOrderSum \n";
			} else if (isElementPathExist && !isAttributePathExist
					&& (numTables > 1)) {
				return _SELECT
						+ "\n"
						+ _FROM
						+ "\n"
						+ _WHERE
						+ "\n"
						+ "ORDER BY DocId, DeweyOrderSum \nOPTION (FORCE ORDER) \n";
			} else {
				return "ERROR";
			}
		}
		return null;
	}

	private ArrayList splitXPathWithPosPredicate(String XPath) {

		String[] result = XPath.split("\\[");
		ArrayList temp = new ArrayList();

		for (int i = 1; i < result.length; i++) {
			if (result[i].contains("]")) {
				if (i == (result.length - 1)) {
					result[i - 1] = result[i - 1] + "[" + result[i];
					result[i] = null;

					MyPath mypath = new MyPath();
					mypath.path = result[i - 1];
					mypath.pathWOpredicate = mypath.path
							.replaceAll(
									"\\[(position\\(\\)(>|<|(<=)|(>=)|=))?(([0-9])+( (to) ([0-9])+)?|(last\\(\\))((-)([0-9])+)?)\\]",
									"");

					if (temp.size() > 0) {
						MyPath tempPath = (MyPath) temp.get(temp.size() - 1);
						mypath.path = tempPath.pathWOpredicate + mypath.path;
						mypath.pathWOpredicate = tempPath.pathWOpredicate
								+ mypath.pathWOpredicate;
					}

					String[] tempLevel = mypath.path.split("\\[");
					tempLevel = tempLevel[0].split("\\/");
					mypath.predLevel = tempLevel.length - 1;

					tempLevel = mypath.pathWOpredicate.split("\\/");
					mypath.level = tempLevel.length - 1;

					String predicate = result[i - 1].substring(result[i - 1]
							.lastIndexOf("[") + 1, result[i - 1]
							.lastIndexOf("]"));
					if (predicate.contains("last()")) {
						computeLastPos(result[i - 1]);
						mypath.initPos = -99999;
						mypath.endPos = 99999;
					}

					if (predicate.startsWith("position()")) {
						String dummy = predicate.replace("position()", "");
						if (dummy.startsWith("<=")) {
							dummy = dummy.replace("<=", "");
							mypath.initPos = 0;
							mypath.endPos = Integer.parseInt(dummy);
						} else if (dummy.startsWith(">=")) {
							dummy = dummy.replace(">=", "");
							mypath.endPos = Integer.parseInt(dummy) - 1;
						} else if (dummy.startsWith("<")) {
							dummy = dummy.replace("<", "");
							mypath.initPos = 0;
							mypath.endPos = Integer.parseInt(dummy) - 1;
						} else if (dummy.startsWith(">")) {
							dummy = dummy.replace(">", "");
							mypath.endPos = Integer.parseInt(dummy);
						} else if (dummy.startsWith("=")) {
							dummy = dummy.replace("=", "");

							if (dummy.contains("to")) {
								String[] X = dummy.split("to");
								mypath.initPos = Integer.parseInt(X[0].trim()) - 1;
								mypath.endPos = Integer.parseInt(X[1].trim());
							} else {
								mypath.initPos = Integer.parseInt(dummy) - 1;
								mypath.endPos = Integer.parseInt(dummy);
							}
						}
					} else {
						mypath.initPos = Integer.parseInt(predicate) - 1;
						mypath.endPos = Integer.parseInt(predicate);
					}
					temp.add(mypath);
				} else {

					int pos = result[i].lastIndexOf("]");
					result[i - 1] = result[i - 1] + "["
							+ result[i].substring(0, pos + 1);
					result[i] = result[i].substring(pos + 1);

					if (result[i].lastIndexOf("/") > 0) {
						if (!result[i].substring(0, result[i].lastIndexOf("/"))
								.equals("/")) {
							result[i - 1] = result[i - 1]
									+ result[i].substring(0, result[i]
											.lastIndexOf("/"));
							result[i] = result[i].substring(result[i]
									.lastIndexOf("/"));
						}
					}
					MyPath mypath = new MyPath();
					mypath.path = result[i - 1];
					mypath.pathWOpredicate = mypath.path
							.replaceAll(
									"\\[(position\\(\\)(>|<|(<=)|(>=)|=))?(([0-9])+( (to) ([0-9])+)?|(last\\(\\))((-)([0-9])+)?)\\]",
									"");

					if (temp.size() > 0) {
						MyPath tempPath = (MyPath) temp.get(temp.size() - 1);
						mypath.path = tempPath.pathWOpredicate + mypath.path;
						mypath.pathWOpredicate = tempPath.pathWOpredicate
								+ mypath.pathWOpredicate;
					}

					String[] tempLevel = mypath.path.split("\\[");
					tempLevel = tempLevel[0].split("\\/");
					mypath.predLevel = tempLevel.length - 1;

					tempLevel = mypath.pathWOpredicate.split("\\/");
					mypath.level = tempLevel.length - 1;

					String predicate = result[i - 1].substring(result[i - 1]
							.lastIndexOf("[") + 1, result[i - 1]
							.lastIndexOf("]"));
					if (predicate.contains("last()")) {
						computeLastPos(result[i - 1]);
						mypath.initPos = -99999;
						mypath.endPos = 99999;
					}

					if (predicate.startsWith("position()")) {
						String dummy = predicate.replace("position()", "");
						if (dummy.startsWith("<=")) {
							dummy = dummy.replace("<=", "");
							mypath.initPos = 0;
							mypath.endPos = Integer.parseInt(dummy);
						} else if (dummy.startsWith(">=")) {
							dummy = dummy.replace(">=", "");
							mypath.endPos = Integer.parseInt(dummy) - 1;
						} else if (dummy.startsWith("<")) {
							dummy = dummy.replace("<", "");
							mypath.initPos = 0;
							mypath.endPos = Integer.parseInt(dummy) - 1;
						} else if (dummy.startsWith(">")) {
							dummy = dummy.replace(">", "");
							mypath.endPos = Integer.parseInt(dummy);
						} else if (dummy.startsWith("=")) {
							dummy = dummy.replace("=", "");

							if (dummy.contains("to")) {
								String[] X = dummy.split("to");
								mypath.initPos = Integer.parseInt(X[0].trim()) - 1;
								mypath.endPos = Integer.parseInt(X[1].trim());
							} else {
								mypath.initPos = Integer.parseInt(dummy) - 1;
								mypath.endPos = Integer.parseInt(dummy);
							}
						} else {
							mypath.initPos = Integer.parseInt(predicate) - 1;
							mypath.endPos = Integer.parseInt(predicate);
						}
					}
					temp.add(mypath);
				}
			}
		}
		return temp;
	}

	private void computeLastPos(String path) {
		try {

			path = path.replace("/", "#.").replace("*", "%").substring(1) + "#";
			Statement statement = dbconnection.createStatement();
			statement.executeUpdate("INSERT INTO TEMPLAST "
					+ "WITH P(PATHID) AS( "
					+ " SELECT MIN(PathID) FROM PATH WHERE PATHEXP LIKE '"
					+ path + "%' AND PATHEXP NOT LIKE '%@%' " + ") "
					+ "SELECT V.DOCID, MAX(V.DEWEYORDERSUM) AS DOS  "
					+ "FROM  P, PATHVALUE V " + "WHERE V.PATHID= P.PATHID "
					+ "OPTION (FORCE ORDER) ");
			statement
					.executeUpdate("INSERT INTO LASTVALUE "
							+ "SELECT R.DOCID, R.LEVEL, ((D.DOS / (R.RValue-1) / 2) + 1) AS LASTVALUE  "
							+ "FROM TEMPLAST D, DOCUMENTRVALUE AS R "
							+ "WHERE D.DOCID = R.DOCID AND R.LEVEL = ");
			statement.close();
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			// JOptionPane.showMessageDialog(null,ex.getMessage(), "Error",
			// JOptionPane.ERROR_MESSAGE);
			// return "ERROR";
		}
	}

	/*
	 * public String getTranslatedSQL() { }
	 */

	private HashMap loadRValue() {
		HashMap RValue = new HashMap();
		try {
			Statement statement = dbconnection.createStatement();
			ResultSet rs = statement
					.executeQuery("SELECT * FROM DOCUMENTRVALUE ");
			while (rs.next()) {
				RValue.put(new Integer(rs.getString("LEVEL")), new Long(rs
						.getString("RVALUE")));
			}
			rs.close();
			statement.close();

		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			// JOptionPane.showMessageDialog(null,ex.getMessage(), "Error",
			// JOptionPane.ERROR_MESSAGE);
			// return "ERROR";
		}
		return RValue;
	}

	private boolean isSingleDoc() {
		try {
			Statement statement = dbconnection.createStatement();
			ResultSet rs = statement
					.executeQuery("SELECT COUNT(*) AS COUNTER FROM DOCUMENT ");
			while (rs.next()) {
				if (rs.getInt("COUNTER") == 1) {
					rs.close();
					statement.close();
					return true;
				}
			}
			rs.close();
			statement.close();
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
			// JOptionPane.showMessageDialog(null,ex.getMessage(), "Error",
			// JOptionPane.ERROR_MESSAGE);
			// return "ERROR";
		}
		return false;
	}

	public boolean isXPathValid(String pattern, String xpath) {
		String[] STemp = xpath.split("\\.");
		String[] PTemp = pattern.split("/");
		int i = 0;
		if (STemp.length >= PTemp.length) {
			boolean isOK = true;
			for (int x = 1; x < PTemp.length; x++) {
				if ((x >= PTemp.length) || ((x + i) >= STemp.length)) {
					isOK = false;
					break;
				}
				if (PTemp[x].equals("*")) {
					continue;
				} else if (PTemp[x].equals("@*")) {
					continue;
				} else if (PTemp[x].length() == 0) {
					if (STemp[x + i].equals(PTemp[x + 1] + "#")) {
						i--;
						x++;
						continue;
					}
					i++;
					if (STemp.length <= (x + i)) {
						isOK = false;
						break;
					}
					x--;
					continue;
				} else if (!STemp[x + i].equals(PTemp[x] + "#")) {
					isOK = false;
					break;
				}
			}
			if (isOK) {
				return true;
			}
		}
		return false;
	}
}
